package com.phuc.game.tankshooter.sprite;

import java.util.ArrayList;

import org.anddev.andengine.entity.IEntity;
import org.anddev.andengine.entity.modifier.ParallelEntityModifier;
import org.anddev.andengine.entity.modifier.PathModifier;
import org.anddev.andengine.entity.modifier.PathModifier.IPathModifierListener;
import org.anddev.andengine.entity.modifier.PathModifier.Path;
import org.anddev.andengine.entity.scene.Scene;
import org.anddev.andengine.entity.sprite.AnimatedSprite;
import org.anddev.andengine.opengl.texture.region.TiledTextureRegion;
import org.anddev.andengine.util.MathUtils;
import org.anddev.andengine.util.constants.TimeConstants;

import com.phuc.game.tankshooter.MainActivity;
import com.phuc.game.tankshooter.common.Utility;
import com.phuc.game.tankshooter.engine.GamePlay;
import com.phuc.game.tankshooter.engine.MovingPathFactory;

public abstract class EnemyObjectSprite extends AnimatedSprite implements TimeConstants {

	public static ArrayList<EnemyObjectSprite> tankEnemy = new ArrayList<EnemyObjectSprite>();
	
	protected int hp;
	protected int hpLeft;
	protected int size;
	protected float speed;
	protected int explodeSize;
	
	private int timeSmoke;
	private int timeReloadSmoke;
	private boolean speedChanged;
	private boolean isEnemy;

	ParallelEntityModifier movingModifier;
	private Path[] movePath;
	private int movePathIndex;

	public EnemyObjectSprite(TiledTextureRegion pTiledTextureRegion, Scene scene,
			float pTileWidth, float pTileHeight) {
		super(-pTileWidth, -pTileHeight, pTileWidth, pTileHeight, pTiledTextureRegion);

		tankEnemy.add(this);
		timeSmoke = 0;
		timeReloadSmoke = -1;
		speedChanged = false;
		isEnemy = true;
		movePathIndex = 0;
		explodeSize = ExplodeSprite.EXPLODE_SIZE_NORMAL;
	}

	public void attacked(int damage) {
		hpLeft -= damage;
		if (hpLeft < 2 * hp / 3 && hpLeft > hp / 3) {
			timeReloadSmoke = 30;
		} else if (hpLeft < hp / 3 && hpLeft > 0 && hpLeft < 70) {
			timeReloadSmoke = 5;
			
			// Neu xe tang con it HP, toc do cham lai, khoi boc nghi ngut
			if (!speedChanged) {
				this.unregisterEntityModifier(movingModifier);
				speed = 3 * speed /2;
				Path newPath = MovingPathFactory.createRandomLinePath_TopToBottom(
						(int)this.getX(), (int)this.getY());
				setPath(new Path[] {newPath});
				moveOnNextPath();
				
				speedChanged = true;
			}
		}
		
		if (hpLeft <= 0) {
			tankEnemy.remove(this);
			MainActivity.getInstant().getGamePlay().createExplodeWithSize(
					getX() + getTankSizeW() / 2, getY(), explodeSize);
			createDead();
			EnemyObjectSprite.this.detachSelf();
			EnemyObjectSprite.this.setIgnoreUpdate(true);
			EnemyObjectSprite.this.clearEntityModifiers();
			EnemyObjectSprite.this.clearUpdateHandlers();
			GamePlay.playExplode();
			if (isEnemy) {
				MainActivity.getInstant().getGamePlay().addPoint(1);
			} else {
				MainActivity.getInstant().getGamePlay().decreaseLife(1);
			}
		}
	}

	public void moveOnNextPath() {
		float speedAfterCalculate = speed;
		float corY1 = movePath[movePathIndex].getCoordinatesY()[0];
		float corY2 = movePath[movePathIndex].getCoordinatesY()[1];
		
		if (corY1 < -MovingPathFactory.SIZE_OBJECT_HEIGHT) {
			speedAfterCalculate = speed * (corY2 - corY1)
					/ (corY2 + MovingPathFactory.SIZE_OBJECT_HEIGHT);
		}

		PathModifier pm = new PathModifier(speedAfterCalculate / (float)movePath.length, movePath[movePathIndex], null,
				new IPathModifierListener() {

					@Override
					public void onPathStarted(PathModifier pPathModifier,
							IEntity pEntity) {
						setRotationFromPath(movePath[movePathIndex]);
					}

					@Override
					public void onPathWaypointStarted(
							PathModifier pPathModifier, IEntity pEntity,
							int pWaypointIndex) { }

					@Override
					public void onPathWaypointFinished(
							PathModifier pPathModifier, IEntity pEntity,
							int pWaypointIndex) { }

					@Override
					public void onPathFinished(PathModifier pPathModifier,
							final IEntity pEntity) {
						if (movePathIndex >= movePath.length - 1) {
							finishMoving();
						} else {
							movePathIndex++;
							moveOnNextPath();
						}
					}
				});
		movingModifier = new ParallelEntityModifier(pm);
		this.registerEntityModifier(movingModifier);
	}
	
	protected void finishMoving() {
		MainActivity.getInstant().runFromUpdateThread(new Runnable() {
			@Override
			public void run() {
				tankEnemy.remove(EnemyObjectSprite.this);
				MainActivity.getInstant().getGamePlay().createExplode(
						getX() + getTankSizeW() / 2, getY() + getTankSizeH() / 2);
				EnemyObjectSprite.this.detachSelf();
				EnemyObjectSprite.this.setIgnoreUpdate(true);
				EnemyObjectSprite.this.clearEntityModifiers();
				EnemyObjectSprite.this.clearUpdateHandlers();
				if (isEnemy) {
					MainActivity.getInstant().getGamePlay().decreaseLife(1);
				}
			}
		});
	}

	@Override
	public void onManagedUpdate(final float pSecondsElapsed) {
		super.onManagedUpdate(pSecondsElapsed);

		// Xu ly xe tang boc khoi
		timeSmoke++;
		if (timeSmoke >= timeReloadSmoke && timeReloadSmoke != -1) {
			if (hpLeft < hp) {
				int xRandom = MathUtils.random(-35, 35);
				MainActivity.getInstant().getGamePlay().createSmoke(
						getX() + getTankSizeW() / 2 + xRandom, getY() + getTankSizeH() / 2, 1);
			}
			timeSmoke = 0;
		}
	}
	
	public int getSize() {
		return size;
	}
	
	public void setPath(Path[] path) {
		this.movePathIndex = 0;
		this.movePath = path;
	}
	
	public abstract int getTankSizeW();
	
	public abstract int getTankSizeH();
	
	public void createDead() {
		MainActivity.getInstant().getGamePlay().createTankDead(
				EnemyObjectSprite.this.getCurrentTileIndex(),
				EnemyObjectSprite.this.getX(), EnemyObjectSprite.this.getY(),
				getTankSizeW() * 9 / 10, getTankSizeH() * 9 / 10, getRotation());
	}
	
	protected void setRotationFromPath(Path path) {
		this.setRotation((float)Utility.getRotationFromLine(
				path.getCoordinatesX()[0],
				path.getCoordinatesY()[0],
				path.getCoordinatesX()[1],
				path.getCoordinatesY()[1]) + 180);
	}
}
